#include "Lex.h"
#include "Util.h"


Lex::Lex()
	: currentToken()
{}


Lex::~Lex(void)
{
}

// read next token
void Lex::nextToken()
{
	std::string token = "";

	char c;

	//	skip the space or tab
	while (std::cin.get(c))
	{
		if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
			break;
	}

	if (std::cin.eof())
	{
		currentToken.set(END, token, 0);
		return;
	}

	token.push_back(c);

	bool contRead = false;	//	if the token is incomplete and need to read more
	switch(c)
	{
		case '(':
			currentToken.set(LEFT_PARENT, token, 0);
			return;
		case ')':
			currentToken.set(RIGHT_PARENT, token, 0);
			return;
		case '.':
			std::cin.get(c);
			if (std::cin.eof())
			{
				currentToken.set(DOT, token, 0);
				return;
			}
			else if (c == '(' || c == ')' || c == ' ' || c == '\t' || c == '\n' || c == '\r')
			{
				currentToken.set(DOT, token, 0);
				std::cin.putback(c);
			}
			else
			{
				token.push_back(c);
				currentToken.set(ERROR, token, 0);
				return;
			}
			break;
		default:
			contRead = true;
	}

	if (contRead)
	{
		std::cin.get(c);

		//	read until space or tab...
		while (std::cin.good())
		{
			if (c == ' ' || c == '\t' || c == '\n' || c == '(' || c == ')' || c == '\r')
			{
				std::cin.putback(c);
				break;
			}
			else
				token.push_back(c);

			std::cin.get(c);
		}

		if (Util::isLiteral(token))
			currentToken.set(LITERAL, token, 0);
		else if (Util::isNumber(token))
			currentToken.set(NUMBER, token, std::atoi(token.c_str()));
		else
			currentToken.set(ERROR, token, 0);
	}

}


// match and consume a token
bool Lex::matchToken(TokenType tokenType)
{
	this->nextToken();

	return (currentToken.type == tokenType);
}


// reset the current token
void Lex::reset(void)
{
	currentToken.set(END, "", 0);
}
